package hyl.core.data;

import hyl.core.MyFun;
import hyl.core.fun.MyByte;
import hyl.core.reflect.MyKryo;

/**
 * ExManager 连续转换器
 * 
 * 用来连续解析和打包 主要针对 过期数据类型 ExData<br>
 * 
 * 只能用于单一线程<br>
 * 
 * 
 * 
 * 我们把连续值交给他,让他逐一分析是否过期<br>
 * 
 * 特别注意 这不是一个线程安全对象,但可以实例化多个对象分别处理<br>
 * 
 * 
 * @author 37798955@qq.com
 *
 * @param <T>
 */
public class ExManager<T> {
	T _数据; // 值
	//byte[] b数据;
	long l时间戳 = 0;
	static MyKryo kryo = MyKryo.getInstance();
	IParse<byte[], T> _转换器 = null;
	public void set转换器(IParse<byte[], T> 解析器) {
		if (解析器==null) {
			_转换器=new IParse<byte[], T>(){
				@Override
				public T s2t(byte[] 对象) {
					return kryo.deserialize(对象);
				}

				@Override
				public byte[] t2s(T 对象) {
					return kryo.serialize(对象);
				}				
			};
		}else
			_转换器 = 解析器;
	}
	/**
	 * 初始化一个空的过期值对象
	 * 
	 * @param 转换器
	 */
	public ExManager(IParse<byte[], T> 转换器) {
		set转换器( 转换器);
	}
	public ExManager() {
		set转换器(null);
	}
	/**
	 * 从数据库读取数据后解析
	 * 
	 * @param 转换器
	 * @param 保存数据
	 */
	public ExManager(IParse<byte[], T> 转换器, byte[] 保存数据) {	
		set转换器( 转换器);
		loadBytes( 保存数据);
	}
	@SuppressWarnings("unchecked")
	protected T s2t(byte[] 数据) {
		T t数据=null;
		if (_转换器==null)
			 t数据=(T)数据;
		else			
			t数据 = _转换器.s2t(数据);		
		return t数据;
				 
	}
	protected byte[] t2s(T 数据) {
		byte[] b数据=null;
		if (_转换器==null)
			b数据=(byte[])数据;
		else			
			b数据 = _转换器.t2s(数据);		
		return b数据;
	}
	/**
	 * 载入数据
	 * 
	 * @param value
	 */
	public  ExManager<T> loadBytes(byte[] 保存数据) {
		l时间戳 = MyFun.byteArray2Long(MyByte.subBytes(保存数据, 0, 8));
		byte [] b数据=MyByte.subBytes(保存数据, 8);
		_数据 = s2t(b数据);		
		return this;
	}
	/**
	 * 更新值
	 * 
	 * @param value 
	 */
	public ExManager<T> setBytes(byte[] value) {
		_数据 = s2t(value);		
		l时间戳 = MyFun.getMs();
		return this;
	}

	/**
	 * 更新值
	 * 
	 * @param value
	 */
	public ExManager<T> setValue(T value) {
		_数据 = value;	
		l时间戳 = MyFun.getMs();
		return this;
	}

	public byte[] getBytes() {
		l时间戳 = MyFun.getMs();
		return t2s(_数据);
	
	}

	public long get时间戳() {
		return l时间戳;
	}

	public T getValue() {
		l时间戳 = MyFun.getMs();
		return _数据;
	}

	public boolean is过期(long 过期毫秒) {
		if (过期毫秒<=0) return false;
		if ((MyFun.getMs() - l时间戳) > 过期毫秒)
			return true;
		else
			return false;
	}

	public byte[] getSaveBytes() {		
		byte [] b数据 =t2s(_数据);
		return MyFun.concat(MyFun.long2ByteArray(l时间戳), b数据);
	}
	/**
	 * 支持多线程转换
	 * @param 值
	 * @return
	 */
	public synchronized byte[] T2Savebytes(T 值) {
		byte [] 数据 = t2s(值);	
		long t时间戳 = MyFun.getMs();
		return MyFun.concat(MyFun.long2ByteArray(t时间戳), 数据);
	}
	/**
	 * 支持多线程转换
	 * @param 值
	 * @return
	 */
	public synchronized byte[] toSavebytes(byte[] 值) {	
		long t时间戳 = MyFun.getMs();
		return MyFun.concat(MyFun.long2ByteArray(t时间戳), 值);
	}
	
	
	
	
	///////////////////////////////////////////////////////////////

	/**
	 * 根据 源数据 构造过期对象
	 * @param 数据
	 * @return
	 */
	public synchronized ExData<T> toExData(byte[] 数据) {
		ExData<T> data=new ExData<T>(_转换器);
		data.loadBytes(数据);
		return data;
	}
}
